package com.greensam.pixelengine.config;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.cfg.CoercionAction;
import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.databind.type.LogicalType;
import com.greensam.pixelengine.utils.DateTimeFormatterUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * json序列化配置
 *
 * @author Macro_Ray
 * @since 2025/6/19 20:59
 */
@Configuration
public class JsonConfig implements WebMvcConfigurer {

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter<?> converter : converters) {
            if (converter instanceof MappingJackson2HttpMessageConverter jacksonConverter) {
                ObjectMapper mapper = jacksonConverter.getObjectMapper();

                // 注册时间类型序列化模块
                registerLocalDateTimeModule(mapper);
                registerLocalDateModule(mapper);
                registerLocalTimeModule(mapper);

                // Long 类型序列化为字符串防止精度丢失
                SimpleModule longModule = new SimpleModule();
                longModule.addSerializer(Long.class, ToStringSerializer.instance);
                longModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
                mapper.registerModule(longModule);

                // 空字符串转 null
                mapper.coercionConfigFor(LogicalType.Enum)
                        .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsNull);

                // 忽略未知字段
                mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

                break;
            }
        }
    }

    private void registerLocalDateTimeModule(ObjectMapper mapper) {
        SimpleModule module = new DateTimeFormatterUtils().localDateTime();
        mapper.registerModule(module);
    }

    private void registerLocalDateModule(ObjectMapper mapper) {
        SimpleModule module = new DateTimeFormatterUtils().localDate();
        mapper.registerModule(module);
    }

    private void registerLocalTimeModule(ObjectMapper mapper) {
        SimpleModule module = new DateTimeFormatterUtils().localTime();
        mapper.registerModule(module);
    }
}
